// fiber_echo_server_concurrent.cpp
#include <boost/fiber/all.hpp>
#include <boost/asio.hpp>
#include <iostream>
#include <memory>
#include <vector>
#include <atomic>

using namespace boost::asio;
using namespace boost::asio::ip;

class EchoServer {
private:
    io_context& io_context_;
    tcp::acceptor acceptor_;
    std::atomic<int> client_count_{0};

public:
    EchoServer(io_context& io_context, short port)
        : io_context_(io_context),
          acceptor_(io_context, tcp::endpoint(tcp::v4(), port)) {
        start_accept();
        // 启动状态报告 fiber
        boost::fibers::fiber([this]() {
            status_reporter();
        }).detach();
    }

private:
    void start_accept() {
        acceptor_.async_accept(
            boost::fibers::asio::yield,
            [this](boost::system::error_code ec, tcp::socket socket) {
                if (!ec) {
                    // 为每个客户端连接创建新的 fiber
                    boost::fibers::fiber([this, socket = std::move(socket)]() mutable {
                        handle_client(std::move(socket));
                    }).detach();
                } else {
                    std::cerr << "Accept error: " << ec.message() << std::endl;
                }
                // 继续接受新连接
                start_accept();
            }
        );
    }

    void handle_client(tcp::socket socket) {
        int client_id = ++client_count_;
        std::cout << "Client " << client_id << " connected from " 
                  << socket.remote_endpoint() << std::endl;

        try {
            std::array<char, 1024> buffer;
            while (true) {
                boost::system::error_code ec;
                size_t length = socket.async_read_some(
                    boost::asio::buffer(buffer),
                    boost::fibers::asio::yield[ec]
                );

                if (ec == boost::asio::error::eof) {
                    std::cout << "Client " << client_id << " disconnected" << std::endl;
                    break;
                } else if (ec) {
                    std::cerr << "Client " << client_id << " read error: " 
                              << ec.message() << std::endl;
                    break;
                }

                std::cout << "Client " << client_id << " sent: " 
                          << std::string(buffer.data(), length);

                // 回显数据
                boost::asio::async_write(
                    socket,
                    boost::asio::buffer(buffer, length),
                    boost::fibers::asio::yield[ec]
                );

                if (ec) {
                    std::cerr << "Client " << client_id << " write error: " 
                              << ec.message() << std::endl;
                    break;
                }
            }
        } catch (const std::exception& e) {
            std::cerr << "Client " << client_id << " exception: " << e.what() << std::endl;
        }
    }

    void status_reporter() {
        while (true) {
            boost::this_fiber::sleep_for(std::chrono::seconds(5));
            std::cout << "Active clients: " << client_count_ << std::endl;
        }
    }
};

int main() {
    try {
        io_context io_context;
        
        // 初始化 fiber 调度算法
        boost::fibers::use_scheduling_algorithm<boost::fibers::asio::round_robin>(io_context);
        
        EchoServer server(io_context, 8080);
        std::cout << "Concurrent Echo server started on port 8080" << std::endl;
        
        // 运行事件循环
        io_context.run();
        
    } catch (std::exception& e) {
        std::cerr << "Exception: " << e.what() << std::endl;
    }
    
    return 0;
}